Source for tax expenditures on the Treasury Department Website: https://home.treasury.gov/policy-issues/tax-policy/tax-expenditures
Source for federal outlays on the Office of Management and Budget website: https://www.whitehouse.gov/omb/supplemental-materials/
tax_long <- gather(base_df, fiscal_year, expenditure, '2018':'2028', factor_key=TRUE)
tax_long$FY2019_to_2028 <- NULL
custom_pal <- c("#3FC1C9", "#B9F3FF", "#8A4DCC", "#4DCC74", "#EEB9FF", "#CC534D", "#CC7776", "#FFF07A")
# These colors are from the brewer 'Dark2' palette
bea_palette <- c("Commerce and housing" = "#3FC1C9", "Income security" = "#ED713A", "Health" = "#7570B3", "Education, training, employment, and social services" = "#E7298A", "International affairs" = "#66A61E","Addendum: Aid to State and local governments:" = "#E6AB02", "General purpose fiscal assistance" = "#A6761D")
iltheme <- theme(plot.title = element_text(color="black", size=22, face="bold", hjust = 0.5, family="Verdana"),
text = element_text(family="Courier New", size=14),
plot.subtitle = element_text(color="#4c4e4d", size=16, hjust=0.5, family = "Verdana"),
axis.title.x = element_text(color="black", size=20, family="Verdana"),
axis.title.y = element_text(color="black", size=20, family="Verdana"),
plot.caption = element_text(color="black", size=14, face="italic"),
axis.text.x = element_text(size=14),
axis.text.y = element_text(size=14),
plot.background=element_rect(fill="#F0F0F0"),
panel.background =element_rect(fill="#F0F0F0"),
panel.grid.minor.y = element_blank(),
axis.ticks = element_blank(),
axis.line = element_line(size=1, color = "Black"),
legend.text = element_text(size=16))
Tax expenditures are what we usually refer to as tax loopholes or tax breaks. The US Department of Treasury classifies these tax provisions as tax “expenditures” in recognition of the fact that they are “often viewed as alternatives to other policy instruments, such as spending or regulatory programs” (Treasury).
In the United States, many policies act though the tax code rather than through fiscal policy. For instance, other developed nations generally provide health care and/or health insurance for all of their citizens directly though national insurance/medical programs. However, in the United States most people receive insurance through their employer, perhaps not even realizing the generous tax treatment they and their employer are receiving.
time_series <- tax_long %>% select(fiscal_year, Category, expenditure) %>% filter(fiscal_year %in% c(2018)) %>%
group_by(fiscal_year, Category) %>% tally(expenditure)
time_series <- mutate(.data = time_series, amount_billions = n/1000)
time_series$n <- NULL
time_series <- arrange(time_series, -amount_billions)
top7 <- top_n(time_series, 7)
bar_to_plot <- ggplot(data=top7, aes(x=reorder(Category, -amount_billions), y=amount_billions, fill=Category)) +
geom_col(position = "dodge", color="black")
labelling <-geom_text(aes(label= c("\n\n\n\n\n\n\n\nCommerce\nand\nHousing",
"\n\nIncome\nSecurity",
"\nHealth",
"Education\nTraining\nEmployment",
"International\nAffairs",
"State/\nLocal\nAid",
"Fiscal\nAssistance"), color="black", vjust=0.5),
position = position_identity(), color="black")
plot1 <- bar_to_plot +
scale_y_continuous(expand = c(0,0),
name = "Tax Expenditures in Billions of Dollars",
labels = scales::dollar_format(accuracy = 1, suffix = 'B')) +
scale_x_discrete() +
labs(title = "The United States spends trillions \nof dollars on tax loopholes each year",
subtitle = "US Federal Government Tax Expenditures In 2018",
caption = "Source: United States. Department of Treasury. Tax Policy: Tax Expenditures.\n*These estimates are made relative to current law as of July 1, 2018",
x = "Category of Tax Break") +
labelling +
iltheme +
theme(legend.position="none",
axis.text.x = element_blank()) +
scale_fill_manual(values=bea_palette)
ggsave(filename = 'visuals/BiggestCategoryOfBreaks.pdf', width = 11, height = 8.5)
last_plot()
Looking at the largest individual tax breaks, it is easy to see the hidden cost of the American approach to health care policy. The deduction for premiums for employer-sponsored health care plans alone costs over $205 billion a year, according to the Department of Treasury. This deduction has also been blamed for pushing up health care spending in general by encouraging more generous plans with lower cost-sharing and less managed care..
taxex <- filter(tax_long, fiscal_year == 2018)
top10 <- top_n(taxex, 10)
top10 <- arrange(top10, -expenditure)
details <- c("Exclusion of employer health care contributions", "Capital gains (15% tax rate on 'long-term' assets)", "Exclusion of net imputed rental income (homeowner benefit)", "Defined contribution employer plans (401(k))", "Defined benefit employer plans (pensions)", "Accelerated depreciation of machinery and equipment", "Reduced tax rate on income of controlled foreign corporations", "Step-up basis of capital gains at death", "Deductibility of charitable contributions", "Capital gains exclusion- home sales")
descr <- labs(title = "The Employer Health Care Deduction\nDwarfs Other Tax Breaks",
subtitle = "Investor & Housing Tax Breaks Are 5/10 of the Most Expensive Tax Breaks",
caption = "Source: United States. Department of Treasury. Tax Policy: Tax Expenditures. \n
* These estimates are made relative to current law as of July 1, 2018",
x = "Description of Tax Break")
expend_plot <- ggplot(data=top10,
aes(x=reorder(details, expenditure),
y=expenditure,
color=Category,
fill=Category)) +
geom_col(color="black") +
coord_flip() +
scale_y_continuous(expand = c(0.005, 0),
name = "Size of Tax Break in Dollars",
labels = scales::dollar_format(scale = .001, accuracy = 1, suffix = 'B')
) +
scale_x_discrete(labels = scales::wrap_format(18)) +
scale_fill_manual(name="Treasury-Assigned Category",
values=bea_palette
) +
descr +
iltheme +
theme(legend.position =c(.8, .2),
legend.text = element_text(size = 12),
legend.title = element_text(size = 14),
axis.text.x = element_text(size=14),
axis.text.y = element_text(size=9)
)
ggsave(filename = 'visuals/BiggestIndividualBreaks.pdf', width = 13, height = 11)
last_plot()
# Prep For Plots 2 & 3: Group by agency name and sum expenditures within the same agency and year.
# * Create a long-form version of the outlays dataset to use in a time-series plot. That is, create one row for each line item (agency name, bureau name, account name, etc.) and fiscal year.
budget_longform <- gather(budg_2019, fiscal_year, expenditure, '1962':'2023', factor_key=TRUE)
## Keep only descriptive column names rather than codes.
keep_cols <- c('Agency Name', 'Bureau Name', 'Account Name', 'Treasury Agency Code', 'Subfunction Title', 'BEA Category', 'Grant/non-grant split' , 'On- or Off- Budget', 'fiscal_year', 'expenditure')
budget_longform <- budget_longform[keep_cols]
# Take the reshaped longform budget data and group by fiscal year and agency name.
outlays <- budget_longform %>% select(fiscal_year, `Agency Name`, expenditure) %>%
group_by(fiscal_year, `Agency Name`) %>%
tally(expenditure)
## Give the expenditures column a descriptive name
outlays <- mutate(.data = outlays, dollars_thousands = n)
outlays$n <- NULL
## Rename `Agency Name` in snake case.
colnames(outlays)[2] <- 'agency_name'
Note: I need to figure out how to add recession shading and add some events, such as the September 11th terrorist attacks and the invasion of Iraq in 2003.
Departments have received differing treatment over the past two decades depending on presidential priorities and world events. We can see the effects of the recession on the highlighted departments. The Department of Treasury, whose outlays usually consist of interest payments, had to massively increase its expenditures in the depths of the financial crisis. The Department of Agriculture saw a stubborn increase in its outlays due to increased usage of SNAP, more commonly known as the food stamp program.
The September 11th 2001 terrorist attacks and the subsequent invasions of Afghanistan and Iraq saw Department of Defense Expenditures soar, until hostilities started to wind down in 2010 or so. The Department of Homeland Security, founded in 2002, has consistently received $50-$100 billion per year. The increase in 2018 funding for both departments is a reflection of the Trump administration’s priorities.
# Filter to the fiscal years 1995 to 2018.
# Filter to only the 12 agencies/departments with the largest budgets.
facet_data <- outlays %>%
filter(fiscal_year %in% c(1998:2019)) %>%
filter(agency_name %in% c("Department of Agriculture",
"Department of Defense--Military Programs",
"Department of Education",
"Department of Homeland Security",
"Department of Labor",
"Department of the Treasury",
"Department of Veterans Affairs",
"Department of Homeland Security", "Department of State", "Department of Justice"))
facet_plot <- facet_data %>% ggplot(aes(x = fiscal_year, y = dollars_thousands, fill = agency_name)) +
annotate(geom = 'rect',
ymin = -Inf,
ymax = Inf,
xmin =10.917,
xmax = 12.5,
fill = 'red',
alpha = 0.2) +
annotate(geom = 'rect',
ymin = -Inf,
ymax = Inf,
xmin = 3.25,
xmax = 3.83,
fill = 'red',
alpha = 0.2) +
annotate(geom = "segment", x = 3.75, xend = 3.75, y = 0, yend=Inf,
fill = 'black',
alpha = 0.7, linetype=3) +
annotate(geom = "text", x = 3.75, y = Inf, hjust=1, vjust=1.0,
fill = 'black',
alpha = 0.7, label="9/11\nTerrorist\nAttacks", size=2) +
annotate(geom = "segment", x = 5.22, xend = 5.22, y = 0, yend=Inf,
fill = 'black',
alpha = 0.7, linetype=3) +
annotate(geom = "text", x = 5.22, y = Inf, hjust=-.1, vjust=1.0,
fill = 'black',
alpha = 0.7, label="Iraq War", size=2) +
annotate(geom = "segment", x = 20.055, xend = 20.055, y = 0, yend=Inf,
fill = 'black',
alpha = 0.7, linetype=2) +
annotate(geom = "text", x = 20.055, y = Inf, hjust=-.1, vjust=1.0,
fill = 'black',
alpha = 0.7, label="Donald Trump\nInaugurated", size=2) +
annotate(geom = "segment", x = 12.055, xend = 12.055, y = 0, yend=Inf,
fill = 'black',
alpha = 0.7, linetype=2) +
annotate(geom = "text", x = 12.055, y = Inf, hjust=-.1, vjust=1.0,
fill = 'black',
alpha = 0.7, label="Barack Obama\nInaugurated", size=2) +
geom_col() +
facet_wrap(~agency_name) +
scale_y_continuous(name = "Outlays",
labels = scales::dollar_format(scale=.000001,
accuracy = 1,
suffix = 'B')) +
scale_x_discrete( breaks=(seq(1998,2019,2)),
labels = (seq(1998,2019,2))
) +
labs(title = "Selected Departmental Outlays Since 1995",
subtitle = "Some agencies, like the Dept of Defense and the Treasury,\n have experienced significant shifts in outlays since 1995.",
caption="Source: United States. Office of Management and Budget. Public Budget Database.",
x = "Fiscal Year",
y = "Outlays") + iltheme +
theme(axis.text.x = element_text(angle = 90),
strip.text = element_text(face = "bold",
size = rel(1.0)),
axis.text = element_text(size=2),
legend.position="none")
ggsave(filename = 'visuals/Outlays_Since1995_FacetWrap.pdf', width = 11, height = 8.5)
last_plot()
top8agencies <- c("Department of Health and Human Services", "Social Security Administration", "Department of the Treasury", "Department of Defense--Military Programs", "Department of Veterans Affairs", "Other Defense Civil Programs", "Office of Personnel Management", "Department of Education")
HHSonly <- budget_longform %>% filter(fiscal_year %in% c(2017) & `Agency Name` %in% top8agencies)
HHS <- HHSonly %>% select(fiscal_year, `Agency Name`, `Bureau Name`, expenditure) %>% filter(expenditure > 1000000) %>% group_by(fiscal_year, `Agency Name`, `Bureau Name`) %>% summarise(exp=sum(expenditure))
projected <- HHS %>% ggplot(aes(area=exp,
fill=`Agency Name`,
label = `Bureau Name`,
subgroup=`Agency Name`)) +
geom_treemap() +
iltheme +
geom_treemap_text(colour="white",
place="center",
grow = TRUE,
reflow = TRUE,
min.size = 1,
padding.x = grid::unit(unit="mm", 2),
padding.y=grid::unit(unit="mm", 2)) +
geom_treemap_subgroup_border(colour = "black", size = 1) +
theme(legend.position="bottom", legend.title = element_text(face = "bold", size=18)) +
scale_fill_brewer(palette = "Dark2",
labels = scales::wrap_format(16),
name="Agency/Dept") +
scale_size_area() +
labs(title = "Social Security, Medicare/Medicaid,\nand Interest on Debt Dominate the Budget",
subtitle = "Colors Correspond to Agencies, Smaller Boxes to Bureaus or Bureau Equivalents",
caption = "Source: United States. Office of Management and Budget. Public Budget Database.")
ggsave(filename = 'visuals/TreemapTop8.pdf', width = 11, height = 8.5)
last_plot()
I’m still not quite sure what to do with this graphic. I need to clean it up, obviously.
The share of federal spending classified as mandatory has grown as a percentage of total spending since the 1960s.
Mandatory spending is spending controlled by laws other than annual appropriations acts. This spending has been mandated by Congress in the past and does does have to be reappropriated each year. Most mandatory programs are fall under health care (e.g. Medicare, Medicaid), social security, and other income support programs. Spending on mandatory programs is determined by the number of eligible recipients.
Discretionary spending must be appropriated each year by the House and Senate. The largest portion of discretionary spending is funding for the Department of Defense and other defense-related programs. Non-defense discretionary spending, just under half of total discretionary spending in 2018, accounts for all federal spending on diplomacy, education, transportation, research, law enforcement, and paying for the operations of the federal government.
The federal government can borrow money, or collect taxes/revenues to finance its activities. Revenues can be collected from individuals or businesses, through fees, sales taxes, profit taxes, payroll taxes, or through tariffs- taxes on foreign goods.
Since 1962, the proportion of revenue collected through payroll taxes and individual income taxes has increased substantially. The proportion of revenues collected through the corporate income tax and excise taxes (sales taxes, such as the federal gasoline tax) has fallen. The share of revenue from payroll taxes has increased from about 20% of revenues in 1962, to about 35% in 2018. Individual income taxes have gone from a little over 40% of revenues to almost 50% of all federal revenue.
percent_gdp <- read_csv("raw_data/PercentOfGDP.csv")
ggplot(data=percent_gdp, aes(x = `Fiscal Year`, y = `Total Revenues`)) +
geom_line(color = "green",
size = 0.75) +
geom_line(aes(x=`Fiscal Year`,
y = `Total Expenditures`),
size = 0.75,
color = "red")+
geom_col(aes(x=`Fiscal Year`,
y = `Total Expenditures`-`Total Revenues`),
color="black") +
labs(title = "The United States Has Run Deficits For\nMost of the Post-WW2 Era",
subtitle = "More recent deficits are due to tax cuts and a temporary\nincrease in spending and loss of revenues during the Great Recession",
caption="Source: United States. Office of Management and Budget. Public Budget Database.",
x = "Fiscal Year",
y = "Percent of GDP") +
iltheme +
geom_abline(intercept = 0,
slope = 0,
color="black") +
annotate(geom = "text", x = 2010, y = .40,
fill = 'black',
alpha = 1,
label="Total Govt\nExpenditures",
size = 6) +
annotate(geom = "text", x = 2010, y = .20,
fill = 'black',
alpha = 1,
label="Total Govt\nRevenues",
size = 6) +
annotate(geom = "text", x = 1979, y = .15,
fill = 'black',
alpha = 1,
label="Yearly Budget Surplus/Deficit",
size = 6) +
annotate(geom = "segment",
x = 1979, y = .125 ,
xend = 1979, yend = .05) +
scale_y_continuous(limits = c(-.05,0.45),
labels = scales::percent_format(),
breaks = seq(-0.05,0.4,by=.05),
expand = c(0,0),
name="Percent of GDP") +
scale_x_continuous(breaks = (seq(1948,2017,4)),
labels = (seq(1948,2017,4)),
expand = c(0,0)) +
theme(axis.line.x.bottom = element_blank(),
panel.grid.minor = element_blank(),
axis.text.x = element_text(angle = 90))
In Fiscal Year 2018, the federal government was projected to grant about $728 billion to state and local governments. According to the Congressional Research Service, federal grants make up one-third of state spending, and more than half of state spending on health care and other public assistance programs.
breaks <- quantile(x = joined$`2018 grant per capita`,seq(0,1,.20))
bins <- cut(joined$`2018 grant per capita`, unique(breaks), include.lowest=TRUE)
joined$bins <- bins
# Create a list of states that expanded Medicaid by the beginning of 2018, since grants seem to be strongly related to Medicaid expansion.
expanded <- c("AK", "HI", "NM", "AZ", "CA", "CO", "NV", "OR", "WA", "MT", "ND", "MN", "AR", "LA", "IA", "MI", "IL", "IN", "OH", "KY", "WV", "DC", "MD", "DE", "CT", "NJ", "PA", "CT", "RI", "MA", "NH", "VT", "NY")
bin_labels <- c("$1,120 - $1,450", "$1,451 - $1,660", "$1,661 - $2,020", "$2,021 - $2,460", "$2,461 - $5,020")
mapped_pc <- ggplot(data=joined) +
geom_sf(aes(fill = (bins)),color="black", size=1.5) +
geom_sf(data = filter(joined, STUSPS %in% expanded),
aes(fill = bins),
color="#974ea2", size=2, show.legend = FALSE) +
annotate(geom = "text",
x = -65,
y = 35,
label = "States Outlined in Purple Expanded\nMedicaid by the Beginning of 2018",
size = 6) +
coord_sf(xlim = c(-130, -65),
ylim = c(20, 50),
expand = FALSE) +
scale_fill_brewer(name="Per Capita\nFederal Grant",
palette = "Greens",
type = "div",
labels = bin_labels) +
iltheme +
theme(axis.line = element_blank(),
legend.background = element_rect(size=1,
linetype="solid",
colour ="black"),
panel.background = element_rect(fill = NA, size = .2),
legend.position=c(.9, .2)) + xlab("Longitude") + ylab("Latitude")
column_pc <- ggplot(data = joined, aes(x = reorder(STUSPS, -`2018 grant per capita`), y = `2018 grant per capita`)) +
geom_col(aes(fill = bins), color="black") +
geom_col(data = filter(joined, STUSPS %in% expanded),
aes(fill = bins, labels=STUSPS),
color="#974ea2", size=1.2) +
iltheme +
scale_fill_brewer(name="Per Capita\nFederal Grant",
palette = "Greens",
type = "div",
labels = bin_labels) +
scale_y_continuous(name="Amount",
labels = scales::dollar_format(),
expand = c(0,0)) +
scale_x_discrete(name="State") +
theme(axis.text.x.bottom = element_text(angle = 90),
panel.grid = element_blank(),
axis.text.x = element_text(size=16),
legend.background = element_rect(size=1,
linetype="solid",
colour ="black"),
panel.background = element_rect(fill = NA, size = 1),
panel.ontop = TRUE,
legend.position=c(.8, .6))
multiplot <- ggplot() + coord_equal(xlim = c(0, 4),
ylim = c(0, 4), expand = FALSE) +
annotation_custom(ggplotGrob(mapped_pc), xmin = 0, xmax = 4,
ymin = 2, ymax = 4) +
annotation_custom(ggplotGrob(column_pc), xmin = 0, xmax = 4,
ymin = 0, ymax = 2)
ggsave("visuals/PerCapMap.pdf", plot = mapped_pc)
ggsave("visuals/MulttiPerCapMap.pdf", plot = multiplot)
ggsave("visuals/ColumnPerCapMap.pdf", plot = column_pc, width = 11, heigh = 8.5)
multiplot